package com.bblocks.auth.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.bblocks.util.KryoRedisSerializer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.CacheKeyPrefix;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

@Slf4j
//@EnableCaching
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
    /**
     * 缓存key添加部分（主要尝试下kryo ，数据单独添加再kryo下）
     */
    private static final String SYSTEMCACHE_REDIS_KEY_ADD = "kryo2:";

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory
            , Jackson2JsonRedisSerializer redisSerializer
    ) {
        RedisCacheWriter cacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);
        RedisCacheManager manager =  new RedisCacheManager(
		            RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory),

                this.getRedisCacheConfigurationWithTtl(60*15,redisSerializer), // 15分钟，后面改成900秒=15分钟
//	            this.getRedisCacheConfigurationWithTtl(5), // 测试用5秒
                this.getRedisCacheConfigurationMap(redisSerializer) // 指定 key 策略
        );
        return manager;
    }

    private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds,Jackson2JsonRedisSerializer redisSerializer) {

        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = null;//默认的
        if(redisSerializer == null){
            jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);

            ObjectMapper om = new ObjectMapper();
            om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
            jackson2JsonRedisSerializer.setObjectMapper(om);
        }

        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(seconds))
                // 设置key的序列化方式
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))
                // 设置value的序列化方式
                .serializeValuesWith(RedisSerializationContext
                        .SerializationPair
                        .fromSerializer(redisSerializer!=null?redisSerializer:jackson2JsonRedisSerializer)
                )
                // 不缓存null值
                //.disableCachingNullValues()
                ;
               /* if(redisSerializer != null){
                    //config.computePrefixWith(cacheKeyPrefix());// 设置前缀(可能会导致 缓存主动刷新失效)
                    config.prefixCacheNameWith(SYSTEMCACHE_REDIS_KEY_ADD);
                }*/

        return config;
    }

    private Map<String, RedisCacheConfiguration> getRedisCacheConfigurationMap(RedisSerializer redisSerializer) {
        Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>();

       // redisCacheConfigurationMap.put("SysArea", this.getRedisCacheConfigurationWithTtl(24*60*60));//1天




        return redisCacheConfigurationMap;
    }

    // key键序列化方式
    @Bean
    public RedisSerializer<String> keySerializer() {
        return new StringRedisSerializer();
    }

   // @Bean
    public KryoRedisSerializer kryoRedisSerializer(){
        KryoRedisSerializer<Object> kryoRedisSerializer = new KryoRedisSerializer<>(Object.class);
        return kryoRedisSerializer;
    }
	@Bean
	public Jackson2JsonRedisSerializer jackson2JsonRedisSerializer(){
		Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = null;//默认的
		jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);

		ObjectMapper om = new ObjectMapper();
		om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
		om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
		jackson2JsonRedisSerializer.setObjectMapper(om);

		return  jackson2JsonRedisSerializer;
	}

    //@Bean
    public CacheKeyPrefix cacheKeyPrefix() {
        return new CacheKeyPrefix() {
            @Override
            public String compute(String cacheName) {
                StringBuilder sBuilder = new StringBuilder(100);
                //sBuilder.append(SYSTEMCACHE_REDIS_KEY_PREFIX).append(":");
                sBuilder.append(cacheName).append(":").append(SYSTEMCACHE_REDIS_KEY_ADD).append(":");
                return sBuilder.toString();
            }
        };
    }



}
